distHam([],[],0).
distHam([X|Xs], [X|Ys], R) :- member(X, [0,1]), length(Xs, N), length(Ys, N), distHam(Xs, Ys, R).
distHam([X|Xs], [Y|Ys], R) :- member(X, [0,1]), member(Y, [0,1]),  X\=Y, length(Xs, N), length(Ys, N), distHam(Xs, Ys, Q), R is Q + 1.

%------------------------------------------------------------------------------------------------------------%

hastaNDigitos01(0,[]).
hastaNDigitos01(N,[D|Ds]) :- N > 0, member(D,[0,1]), N1 is N - 1, hastaNDigitos01(N1,Ds).

todosHasta(N,S) :- between(0,N,Z), hastaNDigitos01(Z,S).

sonTodos01(Xs) :- length(Xs,X), hastaNDigitos01(X,Xs).

longPrefijoComun([],_,0).
longPrefijoComun(_,[],0).
longPrefijoComun([X|_],[Y|_],0):- member(X,[0,1]), member(Y,[0,1]), X\==Y.
longPrefijoComun([X|Xs],[X|Ys],R):- member(X,[0,1]), longPrefijoComun(Xs,Ys,Q) , R is Q+1.

distPref(Xs,Ys,R) :- not(ground(R)), sonTodos01(Xs), sonTodos01(Ys), length(Xs,X), length(Ys,Y), longPrefijoComun(Xs,Ys,P), R is X + Y - P - P. 
distPref(Xs,Ys,R) :- ground(R), length(Xs,X), L is R+X+X , sonTodos01(Xs), todosHasta(L,Ys),  length(Ys,Y), longPrefijoComun(Xs,Ys,P), R is X + Y - P - P. 


%---------------------------------------------------------------------------------------------------------------%

%calcDistEd(+S,+T,?N)

calcDistEd([],T,N) :- length(T,N),!.
calcDistEd(S,[],N) :- length(S,N),!.
calcDistEd([X|Y],[X|Z],R) :- calcDistEd(Y,Z,R),!.
calcDistEd([A|Y],[B|Z],R) :- A \= B,calcDistEd([A|Y],Z,P),
								calcDistEd(Y,Z,S),
								calcDistEd(Y,[B|Z],Q),
								R is min(S,min(P,Q))+1, !.

%distEd(?S,?T,?N)					
distEd(S,T,N) :- ground(S), soyUnaListaDeCerosYUnos(S), ground(T), soyUnaListaDeCerosYUnos(T), calcDistEd(S,T,N). 
distEd(S,T,N) :- ground(S), soyUnaListaDeCerosYUnos(S), not(ground(T)), ground(N), length(S,Q), R is Q+N, todosHasta(R,T), calcDistEd(S,T,N). 
distEd(S,T,N) :- ground(S), soyUnaListaDeCerosYUnos(S), not(ground(T)), not(ground(N)), soyUnaListaDeCerosYUnos(T), length(T,R), todosHasta(R,T), calcDistEd(S,T,N). 

distEd(S,T,N) :- not(ground(S)), ground(T), distEd(T, S, N). 

distEd(S,T,N) :- not(ground(S)), not(ground(T)), var(S), var(T), mayor(0, I), medio(0, I, Ls), hastaNDigitos01(Ls,S), Lt is I - Ls, hastaNDigitos01(Lt,T), calcDistEd(S,T,N).

distEd(S,T,N) :- not(ground(S)), not(ground(T)), not(var(S)), esInf(S), soyUnaListaDeCerosYUnos(S), var(T), mayor(0, I), medio(0, I, Ls), hastaNDigitos01(Ls,S), Lt is I - Ls, hastaNDigitos01(Lt,T), calcDistEd(S,T,N). 
distEd(S,T,N) :- not(ground(S)), not(ground(T)), not(var(S)), not(esInf(S)), soyUnaListaDeCerosYUnos(S), var(T), mayor(0, Lt), length(S, I), medio(0, I, Ls), hastaNDigitos01(Ls,S), hastaNDigitos01(Lt,T), calcDistEd(S,T,N). 

distEd(S,T,N) :- not(ground(S)), not(ground(T)), var(S), not(var(T)), soyUnaListaDeCerosYUnos(T), mayor(0, I), medio(0, I, Ls), hastaNDigitos01(Ls,S), Lt is I - Ls, hastaNDigitos01(Lt,T), calcDistEd(S,T,N).

distEd(S,T,N) :- not(ground(S)), not(ground(T)), not(var(T)), soyUnaListaDeCerosYUnos(T), not(var(S)), soyUnaListaDeCerosYUnos(S), not(esInf(S)), not(esInf(T)), length(S, Ls), length(T, Lt), hastaNDigitos01(Ls,S), hastaNDigitos01(Lt,T), calcDistEd(S,T,N). 
distEd(S,T,N) :- not(ground(S)), not(ground(T)), not(var(T)), soyUnaListaDeCerosYUnos(T), not(var(S)), soyUnaListaDeCerosYUnos(S), esInf(S), esInf(T), mayor(0, I), medio(0, I, Ls), hastaNDigitos01(Ls,S), Lt is I - Ls, hastaNDigitos01(Lt,T), calcDistEd(S,T,N). 

distEd(S,T,N) :- not(ground(S)), not(ground(T)), not(var(T)), soyUnaListaDeCerosYUnos(T), not(var(S)), soyUnaListaDeCerosYUnos(S), not(esInf(S)), esInf(T), length(S, I), mayor(0, Lt), medio(0, I, Ls), hastaNDigitos01(Ls,S), hastaNDigitos01(Lt,T), calcDistEd(S,T,N). 
distEd(S,T,N) :- not(ground(S)), not(ground(T)), not(var(T)), soyUnaListaDeCerosYUnos(T), not(var(S)), soyUnaListaDeCerosYUnos(S), esInf(S), not(esInf(T)), length(T, I), mayor(0, Ls), medio(0, I, Lt), hastaNDigitos01(Ls,S), hastaNDigitos01(Lt,T), calcDistEd(S,T,N). 


esInf(Xs) :- var(Xs), !.
esInf([_|Xs]) :- esInf(Xs), !.


medio(X, Y, X):- X=<Y.
medio(X, Y, Z):- X<Y, W is X + 1, medio(W, Y, Z).

mayor(X, X).
mayor(X, Y):- W is X+1, mayor(W, Y).

soyUnaListaDeCerosYUnos([]) :- !.
soyUnaListaDeCerosYUnos(S) :- member(S,[[X|Xs]]), var(X), var(Xs), !.
soyUnaListaDeCerosYUnos(S) :- member(S,[[X|Xs]]), not(var(X)), member(X,[0,1]), var(Xs), !.
soyUnaListaDeCerosYUnos(S) :- member(S,[[X|Xs]]), var(X), not(var(Xs)), soyUnaListaDeCerosYUnos(Xs), !.
soyUnaListaDeCerosYUnos(S) :- member(S,[[X|Xs]]), not(var(X)), member(X,[0,1]), not(var(Xs)), soyUnaListaDeCerosYUnos(Xs), !.